#include "core.h"
#include "ComputureMgr.h"
#include "AsioTcpLink.h"
#include "AsioTcpLinkClient.h"
#include "NetMgr.h"
#include "LogMgr.h"
#include "ServerCore.h"

CSrvComputure::CSrvComputure() 
: xObjBase(CGuidMgr::ENTITY_SERVER)
, m_nSrvIndex (0)
, m_nPlayers(0)
{

}

CSrvComputure::~CSrvComputure()
{

}

void CSrvComputure::SendMsg2Server(xMSG& msg)
{
	CServerCore* core = CServerCore::getInstance();
	if (core)
	{
		core->SendMsg2Net(getBindGuid(), msg);
	}
}

void CSrvComputure::onUnBind()
{
	xObjBase::onUnBind();
	CComputureMgr::getInstance()->ClearServer(m_uuGuid);
}

//-----------------------------------------------------------------------------------------
IMP_SINGLETON_CLASS(CComputureMgr)

void CComputureMgr::AddServer(CAsioTcpLink* pClient, MYTH::SrvReg* pReg)
{
	if (pClient && pReg)
	{
		std::string strIPPort = pReg->srv_ip_port();
		ClearServer(strIPPort);

		CSrvComputure* pSrv = new CSrvComputure;
		if (pSrv)
		{
			if (pClient->getEntityType() == CGuidMgr::ENTITY_LINKS)
			{
				pClient->setReoteNetType(static_cast<ENetDef::_eNet>(pReg->local_type()));
			}

			pSrv->setm_eSrvType(pClient->getRemoteNetType());
			pSrv->setm_strIPPort(strIPPort);
			pSrv->setBindGuid(pClient->getGuid());
			pClient->setBindGuid(pSrv->getGuid());
			pSrv->setm_nSrvIndex(pReg->srv_index());

			m_mapComputureMgr.insert(std::pair<std::string, xObjBase* >(strIPPort, pSrv));
			GAMELOGER->debug("AddServer type=%d, ip=%s, index=%d", 
				pSrv->getm_eSrvType(), pSrv->getm_strIPPort().c_str(), pSrv->getm_nSrvIndex());
		}
	}
}

void CComputureMgr::ClearServer(U64 uGuid)
{
	for(boost::unordered_map<std::string, xObjBase*>::iterator it = m_mapComputureMgr.begin(); it != m_mapComputureMgr.end(); ++it)
	{
		xObjBase* pSrv = it->second;
		if (pSrv->getGuid() == uGuid)
		{
			U64 uBindGuid = pSrv->getBindGuid();
			if (uBindGuid != 0)
			{
				CNetMgr::getInstance()->deleteNet(uBindGuid);
				pSrv->clearBindGuid();
			}
			delete pSrv;
			m_mapComputureMgr.erase(it);
			break; //f**k
		}
	}
}

void CComputureMgr::ClearServer(std::string ip_port)
{
	boost::unordered_map<std::string, xObjBase*>::iterator it = m_mapComputureMgr.find(ip_port);
	if (it != m_mapComputureMgr.end())
	{
		xObjBase* pSrv = it->second;
		U64 uBindGuid = pSrv->getBindGuid();
		if (uBindGuid != 0)
		{
			CNetMgr::getInstance()->deleteNet(uBindGuid);
			pSrv->clearBindGuid();
		}
		delete pSrv;
		m_mapComputureMgr.erase(it);
	}
}

void CComputureMgr::GetAllSrvs(MYTH::SrvReg_R& r)
{
	for(boost::unordered_map<std::string, xObjBase*>::iterator it = m_mapComputureMgr.begin(); it != m_mapComputureMgr.end(); ++it)
	{
		xObjBase* pBase = it->second;
		CSrvComputure* pS = dynamic_cast<CSrvComputure*>(pBase);
		if (pS)
		{
			MYTH::Srv* pSrv = r.add_srvlist();
			pSrv->set_srv_index(pS->getm_nSrvIndex());
			pSrv->set_srv_ip_port(pS->getm_strIPPort());
			pSrv->set_srv_type(pS->getm_eSrvType());
		}
	}
}

CSrvComputure* CComputureMgr::getServer(const std::string& ip_port)
{
	boost::unordered_map<std::string, xObjBase*>::iterator it = m_mapComputureMgr.find(ip_port);
	if (it != m_mapComputureMgr.end())
	{
		return dynamic_cast<CSrvComputure*>(it->second);
	}
	return NULL;
}

void CComputureMgr::SendMsg2AllServer(xMSG& msg)
{
	for(boost::unordered_map<std::string, xObjBase*>::iterator it = m_mapComputureMgr.begin(); it != m_mapComputureMgr.end(); ++it)
	{
		CSrvComputure* pSrv = dynamic_cast<CSrvComputure*>(it->second);
		if (pSrv)
		{
			pSrv->SendMsg2Server(msg);
		}
	}
}

void CComputureMgr::SendMsg2Server(std::string& ip_port, xMSG& msg)
{
	CSrvComputure* pSrv = getServer(ip_port);
	if (pSrv)
	{
		pSrv->SendMsg2Server(msg);
	}
}

void CComputureMgr::SendMsg2Server(ENetDef::_eNet et, xMSG& msg)
{
	for(boost::unordered_map<std::string, xObjBase*>::iterator it = m_mapComputureMgr.begin(); it != m_mapComputureMgr.end(); ++it)
	{
		CSrvComputure* pSrv = dynamic_cast<CSrvComputure*>(it->second);
		if (pSrv)
		{
			if (pSrv->getm_eSrvType() == et)
			{
				pSrv->SendMsg2Server(msg);
			}
		}
	}
}

void CComputureMgr::getTypeSrvList(ENetDef::_eNet et, SrvList& list)
{
	for(boost::unordered_map<std::string, xObjBase*>::iterator it = m_mapComputureMgr.begin(); it != m_mapComputureMgr.end(); ++it)
	{
		CSrvComputure* pSrv = dynamic_cast<CSrvComputure*>(it->second);
		if (pSrv)
		{
			if (pSrv->getm_eSrvType() == et)
			{
				list.push_back(pSrv);
			}
		}
	}
}

CSrvComputure* CComputureMgr::getLightServer(ENetDef::_eNet et)
{
	SrvList srv_list;
	getTypeSrvList(et, srv_list);
	
	U32 count = MAXUINT;
	CSrvComputure* pRet = NULL;
	for (SrvList::iterator it = srv_list.begin(); it != srv_list.end(); it++)
	{
		CSrvComputure* pSrv = *it;
		if (count > pSrv->getm_nPlayers())
		{
			count = pSrv->getm_nPlayers();
			pRet = pSrv;
		}
	}

	return pRet;
}
